/* 
 * Copyright (c) 2002 David Corbin and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.core.internal.api;

import net.sourceforge.perforce.api.IClientApi;
import net.sourceforge.perforce.api.IError;
import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.api.PerforceApiPlugin;
import net.sourceforge.perforce.core.IClientUserListener;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.internal.Policy;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

/**
  * @version 	$Revision: 253 $
  * @author 	<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class Connection 
{
	// --------------------------------------------------------------------------- Private Variables
	
	/** Stores the reference to the Perforce Client API. */
	private IClientApi clientApi;
	/** Stores the Perforce Server to which this connection belongs. */
	private IPerforceServer server;
	/** Stores the timestamp of last use. */
	private long lastUse;
	
	// ------------------------------------------------------------------------- Public Constructors
	
	/** Constructor for Connection. 
	  * 
	  * @param server the server to connect.
	  */
	public Connection(IPerforceServer server)
	{
		this.server = server;
	}
	
	// ------------------------------------------------------------------------------ Public Methods
	
	/** Checks whether the connection is open or not.
	  *
	  * @return true if connection is open. 
	  */
	public boolean isOpen()
	{
		return (clientApi != null && !clientApi.dropped());
	}
	
	/** Opens the connection to the Perforce Server.
	  *
	  * @param monitor for progress feedback. 
	  * @throws PerforceException in case of an error.
	  */
	public void open(IProgressMonitor monitor)
		throws PerforceException
	{
		if (isOpen())
		{
			return;
		}
		else
		{
			if (clientApi != null)
			{
				close();
			}
			
			monitor.beginTask("Opening connection to " + server.getPort(), 100);       //$NON-NLS-1$
			try
			{			
				clientApi = PerforceApiPlugin.createClientApi();
				clientApi.setPort(server.getPort());
				clientApi.setClient(server.getClient());
				clientApi.setUser(server.getUser());				
				clientApi.setPassword(server.getPassword());
				
				String charset = server.getCharset();
				if (charset.length() > 0)
				{
					clientApi.setCharset(charset);
				}
				
				clientApi.setProtocol("tag", "");                        //$NON-NLS-1$ //$NON-NLS-2$
				clientApi.setProtocol("specstring", "");                 //$NON-NLS-1$ //$NON-NLS-2$
				
				monitor.worked(30);
				
				clientApi.init();
				
				monitor.worked(70);
				
				IError error = clientApi.getPerforceError();
				if (error.isError())
				{
					IStatus status = 
						new Status(
							IStatus.ERROR, 
							PerforceCorePlugin.ID, 
							error.getGeneric(), 
							error.format(IError.EF_PLAIN), 
							null);
					
					throw new PerforceException(status);
				}
			}
			finally
			{
				monitor.done();
			}
		}
	}
	
	/** Call this method to run the given IPerforceCommand with the specified arguments.
	  *
	  * @param arguments the arguments.
	  * @param command the command to run.
	  * @param monitor the progress monitor. 
	  */
	public synchronized void run(
		String[] arguments, 
		IPerforceCommand command, 
		IProgressMonitor monitor)
	{
		if (clientApi == null)
		{
			return;
		}
		
		monitor = Policy.monitorFor(monitor);
		monitor.beginTask(
			"p4 " + command.getCommand() + ": ",                         //$NON-NLS-1$ //$NON-NLS-2$
			IProgressMonitor.UNKNOWN);
		try
		{
			synchronized (clientApi)
			{
				final IClientUserListener[] listeners = 
					PerforceCorePlugin.getPlugin().getClientUserListeners();
				for (int i = 0; i < listeners.length; i++)
				{
					listeners[i].run(command, arguments);
				}
				
				clientApi.run(arguments, new ClientUserListenerDelegate(command, listeners));
			}
		}
		finally
		{
			monitor.done();
			lastUse = System.currentTimeMillis();
		}
	}
	
	/** Call this method to close the connection to the Perforce Server. */
	public void close()		
	{
		if (clientApi != null)
		{
			clientApi.dispose();
			clientApi = null;
		}
	}
	
	/** Returns the timestamp of the last use. 
	  *
	  * @return last use timestamp. 
	  */
	public synchronized long getLastUse()
	{
		return lastUse;
	}
}
